package com.shangguigu.queue;

import java.util.Scanner;

/**
 * @author: ZhouBert
 * @date: 2019/9/30
 * @description: 队列是一种有序列表，可以用【数组】或者【链表】实现
 * DataStructure
 * TODO:存在缺陷：1.指针单向移动，会造成元素为空的时候不能添加元素，造成队列不可用的情况！——>运用算法实现环形队列
 */
public class ArrayQueue {

	/**
	 * 队列大小
	 */
	private int maxSize;
	/**
	 * todo:队列头指针。指向队列头部，front 指向队列头的【前一个位置】
	 */
	private int front;

	/**
	 * todo:队列尾指针。指向队列尾部，rear 指向队列尾的【当前位置】
	 */
	private int rear;
	/**
	 * 数据储存
	 */
	private int[] arr;

	/**
	 * 构造大小
	 *
	 * @param maxSize
	 */
	public ArrayQueue(int maxSize) {
		this.maxSize = maxSize;
		arr = new int[maxSize];
		///初始化指针
		front = rear = -1;
	}

	/**
	 * 由于不是环形队列。即使存在出队数据，依然只看尾指针。
	 */
	public boolean isFull() {
		return rear == maxSize - 1;
	}

	/**
	 * 同上。只判断头指针和尾指针是否重合
	 *
	 * @return
	 */
	public boolean isEmpty() {
		return rear == front;
	}


	/**
	 * 元素入队
	 */
	public void queue(int param) {
		///todo:需要判断队列是否已经满了
		if (isFull()) {
			throw new RuntimeException("队列已满！");
		}
		///todo:
//		if (front == -1) {
//			front++;
//		}
		arr[++rear] = param;
	}

	/**
	 * 出队
	 *
	 * @return
	 */
	public int dequeue() {
		if (isEmpty()) {
			throw new RuntimeException("队列已空！");
		}
		return arr[++front];
	}

	/**
	 * 打印所有的数据
	 */
	public void print() {
		if (isEmpty()) {
			throw new RuntimeException("队列已空！");
		}
		for (int i = front + 1; i <= rear; i++) {
			System.out.printf("arr[%d]=%d\n",i,arr[i]);
		}
	}

	/**
	 * 获取队列头一个元素
	 * @return
	 */
	public int getFirst(){
		if(isEmpty()){
			throw new RuntimeException("队列已空！");
		}
		return arr[front+1];
	}

	/**
	 * 获取队列尾一个元素
	 * @return
	 */
	public int getLast(){
		if(isEmpty()){
			throw new RuntimeException("队列已空！");
		}
		return arr[rear];
	}

	/**
	 * 测试基于数组的顺序队列
	 * @param args
	 */
	public static void main(String[] args) {
		ArrayQueue queue = new ArrayQueue(3);
		///todo:接收用户输入
		char key = ' ';
		Scanner scanner = new Scanner(System.in);
		boolean loop = true;
		while(loop) {
			System.out.println("p(print: 打印队列");
			System.out.println("e(exit): 退出程序");
			System.out.println("q(queue): 入队列");
			System.out.println("d(dequeue): 出队列");
			System.out.println("h(head): 查看队列头");
			///todo:获取第一个操作指令
			key = scanner.next().charAt(0);
			switch (key) {
				case 'p':
					try {
						queue.print();
						break;
					}catch (Exception e) {
						// TODO: handle exception
						System.out.println(e.getMessage());
					}

				case 'q':
					System.out.println("输入一个数：");
					int value = scanner.nextInt();
					queue.queue(value);
					break;
				case 'd':
					try {
						int res = queue.dequeue();
						System.out.printf("取出的数据是%d\n", res);
					} catch (Exception e) {
						// TODO: handle exception
						System.out.println(e.getMessage());
					}
					break;
				case 'h':
					try {
						int res = queue.getFirst();
						System.out.printf("队列头的数据是%d\n", res);
					} catch (Exception e) {
						// TODO: handle exception
						System.out.println(e.getMessage());
					}
					break;
				case 'e':
					scanner.close();
					loop = false;
					break;
				default:
					break;
			}
		}

		System.out.println("程序退出~~");
	}
}
